package com.jabo.wechatmomentsdemo.viewmodel;

import android.app.Application;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.MutableLiveData;

import com.jabo.wechatmomentsdemo.http.AbstractCallback;
import com.jabo.wechatmomentsdemo.model.GetMomentsDataModel;
import com.jabo.wechatmomentsdemo.model.GetMomentsDataModelImpl;
import com.jabo.wechatmomentsdemo.model.bean.TweetBean;
import com.jabo.wechatmomentsdemo.model.bean.UserInfo;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import retrofit2.Call;
import retrofit2.Response;

/**
 * @anthor JZheng3
 * @Time: 2020/9/3
 */
public class MainActivityViewModel extends AndroidViewModel {
    private static final String TAG = MainActivityViewModel.class.getSimpleName();
    private static final int FIRST_PAGE = 0;
    private static final int EACH_PAGE_SIZE = 5;

    private int mCurrentPage = FIRST_PAGE;
    private MutableLiveData<UserInfo> mInfoLiveData;
    private GetMomentsDataModel mGetMomentsDataModel;
    private List<TweetBean> mTweetBeans = new ArrayList<>();
    private MutableLiveData<List<TweetBean>> mListTweetBeanLiveData;
    private FilterTweetDataChain mFilterTweetDataChain;

    public MainActivityViewModel(@NonNull Application application) {
        super(application);
        setGetMomentsDataModel(new GetMomentsDataModelImpl());
        mFilterTweetDataChain = new FilterTweetDataChain();
        mTweetBeans.clear();
    }

    public void setGetMomentsDataModel(GetMomentsDataModel getMomentsDataModel) {
        mGetMomentsDataModel = getMomentsDataModel;
    }


    public int getTweetBeansSize() {
        return mTweetBeans.size();
    }

    public MutableLiveData<UserInfo> getInfoLiveData() {
        if (mInfoLiveData == null) {
            mInfoLiveData = new MutableLiveData<>();
        }
        return mInfoLiveData;
    }

    public MutableLiveData<List<TweetBean>> getListTweetBeanLiveData() {
        if (mListTweetBeanLiveData == null) {
            mListTweetBeanLiveData = new MutableLiveData<>();
        }
        return mListTweetBeanLiveData;
    }

    public void getTweetBeanList() {
        mGetMomentsDataModel.getTweetsBeanList().enqueue(new AbstractCallback<List<TweetBean>>() {
            @Override
            protected void onHandleResponse(Call<List<TweetBean>> call, Response<List<TweetBean>> response) {
                mTweetBeans.clear();
                assert response.body() != null;
                mTweetBeans.addAll(response.body());

                //do Filter data
                boolean filterOk = mFilterTweetDataChain
                        .addFilterImpl(new NoContentImageFilter())
                        .filterData(mTweetBeans);
                if (!filterOk) {
                    Log.w(TAG, "onHandleResponse: filterData Error!!!");
                    return;
                }

                if (!mTweetBeans.isEmpty()) {
                    refresh();
                } else {
                    mListTweetBeanLiveData.postValue(mTweetBeans);
                }
            }
        });
    }

    public void getUserInfo() {
        mGetMomentsDataModel.getUserInfo().enqueue(new AbstractCallback<UserInfo>() {
            @Override
            protected void onHandleResponse(Call<UserInfo> call, Response<UserInfo> response) {
                mInfoLiveData.postValue(response.body());
            }
        });
    }

    public void refresh() {
        mCurrentPage = FIRST_PAGE;
        getUserInfo();
        innerLoadData();
    }

    public void loadMore() {
        mCurrentPage++;
        int ceil = (int) Math.ceil((mTweetBeans.size()) * 1.f / EACH_PAGE_SIZE);
        mCurrentPage = Math.min(mCurrentPage, ceil);
        innerLoadData();
    }

    private void innerLoadData() {
        if (mTweetBeans.isEmpty()) {
            getTweetBeanList();
            return;
        }
        //get page data from memory
        int currentPageStartIndex = mCurrentPage * EACH_PAGE_SIZE;
        int wantSize = Math.min(currentPageStartIndex + EACH_PAGE_SIZE, mTweetBeans.size());
        List<TweetBean> tweetBeans = mTweetBeans.subList(currentPageStartIndex, wantSize);
        mListTweetBeanLiveData.postValue(tweetBeans);
    }


    interface FilterListDataAble {
        boolean filterData(List<TweetBean> beans);
    }

    private class FilterTweetDataChain implements FilterListDataAble {
        private List<FilterListDataAble> mFilterListDataAble;

        private FilterTweetDataChain() {
            mFilterListDataAble = new ArrayList<>();
        }

        private FilterListDataAble addFilterImpl(FilterListDataAble filter) {
            if (!mFilterListDataAble.contains(filter)) {
                mFilterListDataAble.add(filter);
            }
            return this;
        }

        private FilterListDataAble removeFilterImpl(FilterListDataAble filter) {
            if (mFilterListDataAble.contains(filter)) {
                mFilterListDataAble.remove(filter);
            }
            return this;
        }

        @Override
        public boolean filterData(List<TweetBean> beans) {
            for (FilterListDataAble filterListDataAble : mFilterListDataAble) {
                if (!filterListDataAble.filterData(beans)) {
                    return false;
                }
            }
            return true;
        }
    }

    class NoContentImageFilter implements FilterListDataAble {
        @Override
        public boolean filterData(List<TweetBean> beans) {
            Log.d(TAG, "start filterData: NoContentImageFilter ");
            Iterator<TweetBean> iterator = beans.iterator();
            while (iterator.hasNext()) {
                TweetBean bean = iterator.next();
                boolean isNoImageAndContent = bean == null
                        || bean.getSender() == null
                        || ((bean.getImages() == null || bean.getImages().isEmpty()) && TextUtils.isEmpty(bean.getContent()));
                if (isNoImageAndContent) {
                    Log.d(TAG, "NoContentImageFilter filter this error data:" + bean);
                    iterator.remove();
                }
            }
            Log.d(TAG, "end filterData: NoContentImageFilter true");
            return true;
        }
    }

    public FilterListDataAble addFilterImpl(FilterListDataAble filter) {
        return mFilterTweetDataChain.addFilterImpl(filter);
    }

    public FilterListDataAble removeFilterImpl(FilterListDataAble filter) {
        return mFilterTweetDataChain.removeFilterImpl(filter);
    }
}
